/*
 * To change this template, choose Tools | Templates
 * and open the template in the editor.
 */

/*
 * FrameApplication_.java
 *
 * Created on Oct 26, 2009, 10:23:36 PM
 */
package com.eduardcapell.lopodder.gui;

import com.eduardcapell.lopodder.beans.Feed;
import com.eduardcapell.lopodder.beans.FeedElement;
import com.eduardcapell.lopodder.db.DBAccess;
import com.eduardcapell.lopodder.io.DownloadLock;
import com.eduardcapell.lopodder.io.DownloadThread;
import com.eduardcapell.lopodder.io.RefreshFeedThread;
import com.eduardcapell.lopodder.io.mp3.SongPlayer;
import com.eduardcapell.lopodder.misc.Utils;
import java.util.ArrayList;
import java.util.List;
import java.util.Observable;
import java.util.Observer;
import java.util.Vector;
import java.util.logging.Level;
import java.util.logging.Logger;
import javax.swing.JDialog;
import javax.swing.JOptionPane;
import javax.swing.event.ListSelectionEvent;
import javax.swing.event.ListSelectionListener;
import javax.swing.table.DefaultTableModel;
import javazoom.jl.player.Player;

/**
 *
 * @author edu
 */
public class FrameApplication extends javax.swing.JFrame
    implements Observer, Runnable, PlayerGUI {

    private List<Feed> feeds;
    private SongPlayer player = null;

    
    public FrameApplication(List<Feed> feeds) {
        this.feeds = feeds;
        initComponents();
        postinit();
    }

    /** This method is called from within the constructor to
     * initialize the form.
     * WARNING: Do NOT modify this code. The content of this method is
     * always regenerated by the Form Editor.
     */
    @SuppressWarnings("unchecked")
    // <editor-fold defaultstate="collapsed" desc="Generated Code">//GEN-BEGIN:initComponents
    private void initComponents() {

        jSplitPane1 = new javax.swing.JSplitPane();
        jScrollPane1 = new javax.swing.JScrollPane();
        jTable1 = new javax.swing.JTable();
        jScrollPane2 = new javax.swing.JScrollPane();
        jTable2 = new javax.swing.JTable();
        jPanel1 = new javax.swing.JPanel();
        jButton1 = new javax.swing.JButton();
        jButton2 = new javax.swing.JButton();
        jButton3 = new javax.swing.JButton();
        jSlider1 = new javax.swing.JSlider();
        jLabel1 = new javax.swing.JLabel();
        jMenuBar1 = new javax.swing.JMenuBar();
        jMenu1 = new javax.swing.JMenu();
        jMenuItem1 = new javax.swing.JMenuItem();
        jMenuItem2 = new javax.swing.JMenuItem();
        jMenuItem3 = new javax.swing.JMenuItem();
        jMenu2 = new javax.swing.JMenu();
        jMenuItem4 = new javax.swing.JMenuItem();
        jMenuItem5 = new javax.swing.JMenuItem();
        jMenuItem6 = new javax.swing.JMenuItem();
        jMenuItem7 = new javax.swing.JMenuItem();
        jMenu3 = new javax.swing.JMenu();
        jMenuItem8 = new javax.swing.JMenuItem();
        jMenuItem9 = new javax.swing.JMenuItem();
        jMenuItem10 = new javax.swing.JMenuItem();
        jMenuItem11 = new javax.swing.JMenuItem();

        setDefaultCloseOperation(javax.swing.WindowConstants.EXIT_ON_CLOSE);
        addWindowListener(new java.awt.event.WindowAdapter() {
            public void windowClosing(java.awt.event.WindowEvent evt) {
                formWindowClosing(evt);
            }
        });

        jSplitPane1.setDividerLocation(100);
        jSplitPane1.setOrientation(javax.swing.JSplitPane.VERTICAL_SPLIT);

        jTable1.setModel(new FeedListTableModel(feeds));
        jTable1.setSelectionMode(javax.swing.ListSelectionModel.SINGLE_SELECTION);
        jScrollPane1.setViewportView(jTable1);

        jSplitPane1.setLeftComponent(jScrollPane1);

        jTable2.setModel(new javax.swing.table.DefaultTableModel(
            new Object [][] {

            },
            new String [] {

            }
        ));
        jTable2.addMouseListener(new java.awt.event.MouseAdapter() {
            public void mouseClicked(java.awt.event.MouseEvent evt) {
                jTable2MouseClicked(evt);
            }
        });
        jScrollPane2.setViewportView(jTable2);

        jSplitPane1.setRightComponent(jScrollPane2);

        getContentPane().add(jSplitPane1, java.awt.BorderLayout.CENTER);

        jPanel1.setLayout(new java.awt.FlowLayout(java.awt.FlowLayout.LEFT));

        jButton1.setText("Play");
        jButton1.addActionListener(new java.awt.event.ActionListener() {
            public void actionPerformed(java.awt.event.ActionEvent evt) {
                jButton1ActionPerformed(evt);
            }
        });
        jPanel1.add(jButton1);

        jButton2.setText("Pause");
        jButton2.addActionListener(new java.awt.event.ActionListener() {
            public void actionPerformed(java.awt.event.ActionEvent evt) {
                jButton2ActionPerformed(evt);
            }
        });
        jPanel1.add(jButton2);

        jButton3.setText("Stop");
        jButton3.addActionListener(new java.awt.event.ActionListener() {
            public void actionPerformed(java.awt.event.ActionEvent evt) {
                jButton3ActionPerformed(evt);
            }
        });
        jPanel1.add(jButton3);

        jSlider1.setMinimumSize(new java.awt.Dimension(60, 16));
        jPanel1.add(jSlider1);

        jLabel1.setText("00:00");
        jPanel1.add(jLabel1);

        getContentPane().add(jPanel1, java.awt.BorderLayout.PAGE_START);

        jMenu1.setText("File");

        jMenuItem1.setText("New Feed");
        jMenuItem1.addActionListener(new java.awt.event.ActionListener() {
            public void actionPerformed(java.awt.event.ActionEvent evt) {
                jMenuItem1ActionPerformed(evt);
            }
        });
        jMenu1.add(jMenuItem1);

        jMenuItem2.setText("Delete Selected Feed");
        jMenuItem2.addActionListener(new java.awt.event.ActionListener() {
            public void actionPerformed(java.awt.event.ActionEvent evt) {
                jMenuItem2ActionPerformed(evt);
            }
        });
        jMenu1.add(jMenuItem2);

        jMenuItem3.setText("Exit");
        jMenuItem3.addActionListener(new java.awt.event.ActionListener() {
            public void actionPerformed(java.awt.event.ActionEvent evt) {
                jMenuItem3ActionPerformed(evt);
            }
        });
        jMenu1.add(jMenuItem3);

        jMenuBar1.add(jMenu1);

        jMenu2.setText("Feeds");

        jMenuItem4.setText("Settings for selected feed");
        jMenuItem4.addActionListener(new java.awt.event.ActionListener() {
            public void actionPerformed(java.awt.event.ActionEvent evt) {
                jMenuItem4ActionPerformed(evt);
            }
        });
        jMenu2.add(jMenuItem4);

        jMenuItem5.setText("Refresh selected");
        jMenuItem5.addActionListener(new java.awt.event.ActionListener() {
            public void actionPerformed(java.awt.event.ActionEvent evt) {
                jMenuItem5ActionPerformed(evt);
            }
        });
        jMenu2.add(jMenuItem5);

        jMenuItem6.setText("Refresh all");
        jMenuItem6.addActionListener(new java.awt.event.ActionListener() {
            public void actionPerformed(java.awt.event.ActionEvent evt) {
                jMenuItem6ActionPerformed(evt);
            }
        });
        jMenu2.add(jMenuItem6);

        jMenuItem7.setText("Download all new episodes");
        jMenuItem7.addActionListener(new java.awt.event.ActionListener() {
            public void actionPerformed(java.awt.event.ActionEvent evt) {
                jMenuItem7ActionPerformed(evt);
            }
        });
        jMenu2.add(jMenuItem7);

        jMenuBar1.add(jMenu2);

        jMenu3.setText("Episodes");

        jMenuItem8.setText("Download selected items");
        jMenuItem8.addActionListener(new java.awt.event.ActionListener() {
            public void actionPerformed(java.awt.event.ActionEvent evt) {
                jMenuItem8ActionPerformed(evt);
            }
        });
        jMenu3.add(jMenuItem8);

        jMenuItem9.setText("Mark selected episodes as downloaded");
        jMenuItem9.addActionListener(new java.awt.event.ActionListener() {
            public void actionPerformed(java.awt.event.ActionEvent evt) {
                jMenuItem9ActionPerformed(evt);
            }
        });
        jMenu3.add(jMenuItem9);

        jMenuItem10.setText("Mark selected episodes as new");
        jMenuItem10.addActionListener(new java.awt.event.ActionListener() {
            public void actionPerformed(java.awt.event.ActionEvent evt) {
                jMenuItem10ActionPerformed(evt);
            }
        });
        jMenu3.add(jMenuItem10);

        jMenuItem11.setText("Download all new episodes for current feed");
        jMenu3.add(jMenuItem11);

        jMenuBar1.add(jMenu3);

        setJMenuBar(jMenuBar1);

        pack();
    }// </editor-fold>//GEN-END:initComponents

    private void formWindowClosing(java.awt.event.WindowEvent evt) {//GEN-FIRST:event_formWindowClosing
        this.addWindowListener(new java.awt.event.WindowAdapter() {

            public void windowClosing(java.awt.event.WindowEvent e) {
                System.out.println("Exiting app...");
                closeDB();
                System.exit(0);
            }

            private void closeDB() {
                try {
                    DBAccess.shutdown();
                } catch (Exception e) {
                    e.printStackTrace();
                }
            }
        });
    }//GEN-LAST:event_formWindowClosing

    private void jMenuItem1ActionPerformed(java.awt.event.ActionEvent evt) {//GEN-FIRST:event_jMenuItem1ActionPerformed
        JDialog newFeed = new NewFeedDialog(FrameApplication.this, feeds);
        Utils.centerWindow(newFeed);
        newFeed.setVisible(true);
        jTable1.updateUI();
    }//GEN-LAST:event_jMenuItem1ActionPerformed

    private void jMenuItem3ActionPerformed(java.awt.event.ActionEvent evt) {//GEN-FIRST:event_jMenuItem3ActionPerformed
        System.out.println("Exiting app...");
        closeDB();
        System.exit(0);
    }//GEN-LAST:event_jMenuItem3ActionPerformed

    private void jMenuItem2ActionPerformed(java.awt.event.ActionEvent evt) {//GEN-FIRST:event_jMenuItem2ActionPerformed
            if (jTable1.getSelectedRow() < 0) {
                JOptionPane.showMessageDialog(FrameApplication.this, "Please select a feed.");
                return;
            }

            int confirmation = JOptionPane.showConfirmDialog(FrameApplication.this,
                "Are you sure?", "Please confirm", JOptionPane.YES_NO_OPTION);

            if (confirmation == JOptionPane.CANCEL_OPTION ||
                confirmation == JOptionPane.NO_OPTION) {
                JOptionPane.showMessageDialog(FrameApplication.this, "Operation cancelled",
                    "User information", JOptionPane.INFORMATION_MESSAGE);
                return;
            }

            DefaultTableModel tm = (DefaultTableModel) jTable1.getModel();
            Vector v = tm.getDataVector();
            Feed f = (Feed) v.get(jTable1.getSelectedRow());

            DBAccess.deleteFeed(f);
            feeds.remove(jTable1.getSelectedRow());
            tableModels();
    }//GEN-LAST:event_jMenuItem2ActionPerformed

    private void jMenuItem5ActionPerformed(java.awt.event.ActionEvent evt) {//GEN-FIRST:event_jMenuItem5ActionPerformed
        DefaultTableModel tm = (DefaultTableModel) jTable1.getModel();
        Vector v = tm.getDataVector();

        if (jTable1.getSelectedRow() < 0)
            return;

        Feed f = (Feed) v.get(jTable1.getSelectedRow());
        f.fetchItems();

        updateFeedElementsTable(f);
    }//GEN-LAST:event_jMenuItem5ActionPerformed

    private void jMenuItem6ActionPerformed(java.awt.event.ActionEvent evt) {//GEN-FIRST:event_jMenuItem6ActionPerformed

        if (DownloadLock.downloading) {
            System.out.println("Already updating...");
            return;
        }
        Thread t = new Thread(new RefreshFeedThread(feeds));
        t.start();
    }//GEN-LAST:event_jMenuItem6ActionPerformed

    private void jMenuItem8ActionPerformed(java.awt.event.ActionEvent evt) {//GEN-FIRST:event_jMenuItem8ActionPerformed
        DefaultTableModel tm = (DefaultTableModel) jTable2.getModel();
        Vector<FeedElement> v = tm.getDataVector();

        if (jTable2.getSelectedRow() < 0)
            return;

        int[] rows = jTable2.getSelectedRows();

        List<FeedElement> toDownload = new ArrayList<FeedElement>();
        for (int i=0; i < rows.length; i++) {
            toDownload.add(v.get(rows[i]));
        }

        for (int i=0; i < toDownload.size(); i++) {
            Feed f = toDownload.get(i).getFeed();
            if (f.getFolder() == null || f.getFolder().length() == 0) {
                System.out.println("Folder is null");
                return;
            }
        }

        try {
            Thread t = DownloadThread.getInstance(toDownload);
            t.start();
        } catch (Exception e1) {
            JOptionPane.showMessageDialog(FrameApplication.this,
                "An error has occurred while trying to download: " + e1.getMessage(),
                "Problem downloading",
                JOptionPane.ERROR_MESSAGE);
            e1.printStackTrace();
        }
    }//GEN-LAST:event_jMenuItem8ActionPerformed

    private void jMenuItem9ActionPerformed(java.awt.event.ActionEvent evt) {//GEN-FIRST:event_jMenuItem9ActionPerformed
        DefaultTableModel tm = (DefaultTableModel) jTable2.getModel();
        Vector<FeedElement> v = tm.getDataVector();

        if (jTable2.getSelectedRow() < 0)
            return;

        int[] rows = jTable2.getSelectedRows();
        for (int i=0; i < rows.length; i++) {
            FeedElement fe = v.get(rows[i]);
            fe.setDownloaded(true);
            DBAccess.updateFeedElement(fe);
        }
    }//GEN-LAST:event_jMenuItem9ActionPerformed

    private void jMenuItem10ActionPerformed(java.awt.event.ActionEvent evt) {//GEN-FIRST:event_jMenuItem10ActionPerformed
        DefaultTableModel tm = (DefaultTableModel) jTable2.getModel();
        Vector<FeedElement> v = tm.getDataVector();

        if (jTable2.getSelectedRow() < 0)
            return;

        int[] rows = jTable2.getSelectedRows();
        for (int i=0; i < rows.length; i++) {
            FeedElement fe = v.get(rows[i]);
            fe.setDownloaded(false);
            DBAccess.updateFeedElement(fe);
        }
    }//GEN-LAST:event_jMenuItem10ActionPerformed

    private void jMenuItem7ActionPerformed(java.awt.event.ActionEvent evt) {//GEN-FIRST:event_jMenuItem7ActionPerformed
        Feed.downloadAllNew(feeds);
    }//GEN-LAST:event_jMenuItem7ActionPerformed

    private void jMenuItem4ActionPerformed(java.awt.event.ActionEvent evt) {//GEN-FIRST:event_jMenuItem4ActionPerformed
        if (jTable1.getSelectedRowCount() != 1) {
            JOptionPane.showMessageDialog(this,
                "Exactly one feed must be selected",
                "Problem with selection",
                JOptionPane.WARNING_MESSAGE);
            return;
        }

        DefaultTableModel tm = (DefaultTableModel) jTable1.getModel();
        Vector v = tm.getDataVector();
        Feed f = (Feed) v.get(jTable1.getSelectedRow());

        JDialog dlg = new FeedSettingsDialog(this, f);
        dlg.setModal(true);
        Utils.centerWindow(dlg);
        dlg.setVisible(true);

        repaint();
        DBAccess.updateFeed(f);
    }//GEN-LAST:event_jMenuItem4ActionPerformed

    private void jTable2MouseClicked(java.awt.event.MouseEvent evt) {//GEN-FIRST:event_jTable2MouseClicked
//        System.out.println("Button: " + evt.getButton());
//        switch (evt.getButton()) {
//            case java.awt.event.MouseEvent.BUTTON3:
//                if (jTable2.getSelectedRowCount() != 1) {
//                    return;
//                }
//                int row = jTable2.getSelectedRow();
//                if (row < 0) {
//                    return;
//                }
//
//                DefaultTableModel tm = (DefaultTableModel) jTable2.getModel();
//                Vector<FeedElement> v = tm.getDataVector();
//                FeedElement fe = v.get(row);
//                System.out.println("Trying to play '" + fe.getFileName() + "'");
//                // TODO Move somewhere else.
//                try {
//                    Player p = new Player(new FileInputStream(new File(fe.getFileName())));
//                    p.play();
//                } catch (Exception ex) {
//                    ex.printStackTrace();
//                }
//                break;
//            default:
//                System.out.println("Other buttons.");
//        }
    }//GEN-LAST:event_jTable2MouseClicked

    private void jButton1ActionPerformed(java.awt.event.ActionEvent evt) {//GEN-FIRST:event_jButton1ActionPerformed
        if (player != null && player.isPlaying()) {
            return;
        }
        int row = jTable2.getSelectedRow();
        if (row < 0) {
            return;
        }
        DefaultTableModel tm = (DefaultTableModel) jTable2.getModel();
        Vector<FeedElement> v = tm.getDataVector();

        FeedElement fe = v.get(row);
        try {
            player = new SongPlayer(fe, this);
            Thread t = new Thread(player);
            t.start();
        } catch (Exception ex) {
            ex.printStackTrace();
        }
        
    }//GEN-LAST:event_jButton1ActionPerformed

    private void jButton2ActionPerformed(java.awt.event.ActionEvent evt) {//GEN-FIRST:event_jButton2ActionPerformed
        if (player == null) {
            return;
        }

        System.out.println("Trying to pause playback.");
        player.pause();
    }//GEN-LAST:event_jButton2ActionPerformed

    private void jButton3ActionPerformed(java.awt.event.ActionEvent evt) {//GEN-FIRST:event_jButton3ActionPerformed
        player.stop();
    }//GEN-LAST:event_jButton3ActionPerformed

    // Variables declaration - do not modify//GEN-BEGIN:variables
    private javax.swing.JButton jButton1;
    private javax.swing.JButton jButton2;
    private javax.swing.JButton jButton3;
    private javax.swing.JLabel jLabel1;
    private javax.swing.JMenu jMenu1;
    private javax.swing.JMenu jMenu2;
    private javax.swing.JMenu jMenu3;
    private javax.swing.JMenuBar jMenuBar1;
    private javax.swing.JMenuItem jMenuItem1;
    private javax.swing.JMenuItem jMenuItem10;
    private javax.swing.JMenuItem jMenuItem11;
    private javax.swing.JMenuItem jMenuItem2;
    private javax.swing.JMenuItem jMenuItem3;
    private javax.swing.JMenuItem jMenuItem4;
    private javax.swing.JMenuItem jMenuItem5;
    private javax.swing.JMenuItem jMenuItem6;
    private javax.swing.JMenuItem jMenuItem7;
    private javax.swing.JMenuItem jMenuItem8;
    private javax.swing.JMenuItem jMenuItem9;
    private javax.swing.JPanel jPanel1;
    private javax.swing.JScrollPane jScrollPane1;
    private javax.swing.JScrollPane jScrollPane2;
    private javax.swing.JSlider jSlider1;
    private javax.swing.JSplitPane jSplitPane1;
    private javax.swing.JTable jTable1;
    private javax.swing.JTable jTable2;
    // End of variables declaration//GEN-END:variables

    private void postinit() {
        tableModels();
    }

    public void update(Observable arg0, Object arg1) {
        repaint();
    }

    public void run() {
        throw new UnsupportedOperationException("Not supported yet.");
    }

    private void closeDB() {
		try {
			DBAccess.shutdown();
		} catch (Exception e) {
			// TODO Auto-generated catch block
			e.printStackTrace();
		}
    }

    private void tableModels() {
        jTable1.getSelectionModel().addListSelectionListener(
            new ListSelectionListener() {
                public void valueChanged(ListSelectionEvent e) {
                    if (e.getValueIsAdjusting()) {
                        return;
                    }

                    if (jTable1.getSelectedRow() < 0) {
                        DefaultTableModel tm2 = new FeedContentsTableModel(null);
                        jTable2.setModel(tm2);
                    } else {
                        DefaultTableModel tm1 = (DefaultTableModel) jTable1.getModel();
                        Vector v = tm1.getDataVector();

                        Feed f = (Feed) v.get(jTable1.getSelectedRow());

                        if (f.isLoadedElements()) {
                            f.preloadItems();
                        } else {
                            f.fetchItems();
                            f.setLoadedElements(true);
                        }
                        updateFeedElementsTable(f);
                    }

                }

                private void updateFeedElementsTable(Feed f) {
                    int n = jTable1.getSelectedRow();
                    if (n >= 0 && n < jTable1.getRowCount()) {
                        DefaultTableModel tm2 = new FeedContentsTableModel(f.getElements());
                        jTable2.setModel(tm2);

                        f.deleteFeedElementsObservers();

                        for (int i=0; i < f.getElements().size(); i++) {
                            FeedElement fe = f.getElements().get(i);
                            fe.addObserver(FrameApplication.this);
                        }
                    }
                }
            }
        );
    }

	private void updateFeedElementsTable(Feed f) {
		int n = jTable1.getSelectedRow();
		if (n >= 0 && n < jTable1.getRowCount()) {
			DefaultTableModel tm2 = new FeedContentsTableModel(f.getElements());
			jTable2.setModel(tm2);

			f.deleteFeedElementsObservers();

			for (int i=0; i < f.getElements().size(); i++) {
				FeedElement fe = f.getElements().get(i);
				fe.addObserver(this);
			}
		}
	}

    public void updateSlider(int percentage) {
        jSlider1.setValue(percentage);
    }

    public void updateTimer(long microseconds) {
        jLabel1.setText(Utils.microsecondsToHoursMinsSeconds(microseconds));
    }
}
